
import { PATH_MODE } from '../common/pathMode.js'
import { toMatrix } from "../math/array.js"
import { _o } from "../math/index.js"
import { _curve, _bezierCurveTo, _moveTo, _quadraticCurveTo } from './curve.js'
import { _circle } from './circle.js'
import { rayMix } from '../math/arrayMix.js';
import { linkPoints, stripPoints, stripLoopPoints, stripFanPoints } from '../algorithm/link.js'
import { _traversal } from '../algorithm/traversal.js'


// 点
export const _points = (points) => {
    let r = 3
    return points.map(t => {
        return _circle({ o: t, r })
    }).join(" ")
}


// 线段
export const _lines = (points, curve) => {
    return _curve({ points, curve, step: 2, discrete: true })
}
// 中心射线
export const _ray = (points, curve) => {
    let o = _o(points)
    let ps = rayMix(o, points)
    return _curve({ points: ps, curve, step: 2 })
}
export const _rayOne = (points, curve) => {
    let o = _o(points)
    return _curve({ points: [o, points[0]], curve })
}

// 带状
const _lineStrip = (points, curve) => {
    return _curve({ points, curve })
}
// LINE_LOOP
export const _lineLoop = (points, curve) => {
    return _curve({ points, curve, loop: true })
}
// 扇
const _rayFan = (points, curve) => {
    return _ray(points, curve) + _lineLoop(points)
}


// 多边形
export const _ploygon = ({ points, n, curve }) => {
    let matrix = toMatrix(points, n)
    return matrix.map(ps => {
        return _curve({ points: ps, curve, loop: true })
    }).join(' ')
}
// 三角形
export const _triangles = (points, curve) => {
    return _ploygon({ points, n: 3, curve })
}

const _serial = (points, n, loop, curve) => {
    let iter = (ps) => {
        return _curve({ points: ps, curve, loop: true })
    }
    return _traversal({
        points,
        n,
        iter,
        loop
    })
}

const _triangleSerial = (points, curve) => {
    let n = 3
    return _serial(points, n, false, curve)
}
const _squareSerial = (points, curve) => {
    let n = 4
    return _serial(points, n, false, curve)
}

const _triangleSerialLoop = (points, curve) => {
    let n = 3
    return _serial(points, n, true, curve)
}
const _squareSerialLoop = (points, curve) => {
    let n = 4
    return _serial(points, n, true, curve)
}

const _curveMode = (points, loop = false) => {
    let n = 3
    return _traversal({
        points,
        n,
        iter: ([p1, p2, p3]) => {
            return _quadraticCurveTo([p2, p3])
        },
        init: _moveTo,
        loop
    }).join(' ')
}

const _curveStrip = (points) => {
    return _curveMode(points, false)
}
// 
const _curveLoop = (points) => {
    return _curveMode(points, true)

}
// 离散
const _discreteBezier = (points) => {
    let n = 4
    let discrete = true
    return _traversal({
        points,
        n,
        iter: ([p1, p2, p3, p4]) => {
            return _moveTo(p1) + ' ' + _bezierCurveTo([p2, p3, p4])
        },
        discrete
    }).join(' ')
}
// 连续
const _bezierMode = (points, loop = false) => {
    let n = 4
    return _traversal({
        points,
        n,
        iter: ([p1, p2, p3, p4]) => {
            return _bezierCurveTo([p2, p3, p4])
        },
        init: _moveTo,
        loop
    }).join(' ')
}
const _bezierStrip = (points) => {
    return _bezierMode(points, false)
}

const _bezierLoop = (points) => {
    return _bezierMode(points, true)
}


const _triangleStrip = (points, curve) => {
    let matrix = stripPoints(points, 3)
    return matrix.map(ps => {
        return _curve({ points: ps, curve, loop: true })
    }).join(' ')
}

const _triangleStripLoop = (points, curve) => {
    let matrix = stripLoopPoints(points, 3)
    return matrix.map(ps => {
        return _curve({ points: ps, curve, loop: true })
    }).join(' ')
}
const _triangleFan = (points, curve) => {
    let matrix = stripFanPoints(points, 2)
    let last = matrix.pop()
    return matrix.map(ps => {
        return _curve({ points: ps, curve })
    }).join(' ') + _curve({ points: last, curve, loop: true })
}


// 四边形
export const _squares = (points, curve) => {
    return _ploygon({ points, n: 4, curve })
}

const _squareStrip = (points, curve) => {
    let matrix = stripPoints(points, 4)
    return matrix.map(ps => {
        return _curve({ points: ps, curve, loop: true })
    }).join(' ')
}

const _squareStripLoop = (points, curve) => {
    let matrix = stripLoopPoints(points, 4)
    return matrix.map(ps => {
        return _curve({ points: ps, curve, loop: true })
    }).join(' ')
}
// 扇线
const _lineFan = (points, curve) => {
    let [p, ...rest] = points
    let ps = rayMix(p, rest)
    return _curve({ points: ps, curve })
}

export const _link = (points, curve) => {
    let lps = linkPoints(points)
    return _curve({ points: lps, curve, step: 2 })
}
const pathModeMapFn = {
    [PATH_MODE.LINE_STRIP]: _lineStrip,
    [PATH_MODE.LINE_LOOP]: _lineLoop,
    [PATH_MODE.POINTS]: _points,
    [PATH_MODE.LINES]: _lines,
    [PATH_MODE.TRIANGLES]: _triangles,
    [PATH_MODE.TRIANGLE_SERIAL]: _triangleSerial,
    [PATH_MODE.TRIANGLE_SERIAL_LOOP]: _triangleSerialLoop,
    [PATH_MODE.SQUARES]: _squares,
    [PATH_MODE.LINE_FAN]: _lineFan,
    [PATH_MODE.RAY]: _ray,
    [PATH_MODE.RAY_FAN]: _rayFan,
    [PATH_MODE.LINK]: _link,
    [PATH_MODE.TRIANGLE_STRIP]: _triangleStrip,
    [PATH_MODE.SQUARE_STRIP]: _squareStrip,
    [PATH_MODE.TRIANGLE_STRIP_LOOP]: _triangleStripLoop,
    [PATH_MODE.SQUARE_STRIP_LOOP]: _squareStripLoop,
    [PATH_MODE.SQUARE_SERIAL]: _squareSerial,
    [PATH_MODE.SQUARE_SERIAL_LOOP]: _squareSerialLoop,
    [PATH_MODE.TRIANGLE_FAN]: _triangleFan,
    [PATH_MODE.CURVE_STRIP]: _curveStrip,
    [PATH_MODE.CURVE_LOOP]: _curveLoop,
    [PATH_MODE.BEZIER_STRIP]: _bezierStrip,
    [PATH_MODE.BEZIER_LOOP]: _bezierLoop,
    [PATH_MODE.DISCRETE_BEZIER]: _discreteBezier

}

export const _pathMode = ({ pathMode, points, curve, closed }) => {
    if (closed && !pathMode) {
        pathMode = PATH_MODE.LINE_LOOP
    }
    let fn = pathModeMapFn[pathMode] || _lineStrip
    return fn(points, curve)
}